﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.Cors;
using WebApiFrameworkJWTDemo.Api.Filters;
using WebApiFrameworkJWTDemo.Common;
using WebApiFrameworkJWTDemo.Model;

namespace WebApiFrameworkJWTDemo.Api.Controllers
{
    /***
     * 1.把校验过程从客户端搬到服务器，不容易被人篡改 
     * 2.用户登陆成功后服务器给用户一个加密串代表登陆人的身份
     * 3.服务器通过判断headers中的key是否存在来判断用户是否登录
     * 4.通过特性的方式进行jwt校验
     * 5.在校验时读取jwt中的账号信息并存入User.Identity.Name
     * 6.可以在任意Action方法中读取User.Identity.Name
     */
    [RoutePrefix("api/User")]
    [EnableCors(origins: "http://127.0.0.1:5500,http://127.0.0.1:5501", headers: "*", methods: "*")]
    public class UserController : ApiController
    {
        [HttpPost]
        [Route("Login")]
        public ResponseResult Login(LoginViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return new ResponseResult() { Success = false, ErrorMsg = ModelState.Values.ElementAt(0).Errors[0].ErrorMessage };
            }
            if ((model.LoginName ?? "").Length > 2 && string.Equals(model.Password, "12345"))
            {
                #region 不加JWT用户登录校验
                //return new ResponseResult() { Success = true, Data = "model.LoginName=" + model.LoginName + ", model.Password=" + model.Password };
                #endregion

                #region 加上JWT用户登录校验
                return new ResponseResult() { Success = true, Data = JWTUtil.Encode(model) };
                #endregion
            }
            return new ResponseResult() { Success = false, ErrorMsg = "用户名或密码错误" };
        }

        [HttpGet]
        [Route("Message")]
        public IHttpActionResult GetMessage()
        {
            //return Ok("data");
            return Ok(new Student() { Id = 1, Name = "Guo" });
            //return NotFound();
            //return InternalServerError(new Exception("自定义异常内容"));
        }

        #region GetUserInfo()不加JWT用户登录校验
        //[Route("GetUserInfo")]
        //public ResponseResult GetUserInfo(string loginName)
        //{
        //    return new ResponseResult() { Success = true, Data = loginName + "用户资料" };
        //}
        #endregion

        #region GetUserInfo()加上JWT用户登录校验
        //[Route("GetUserInfo")]
        //public ResponseResult GetUserInfo()
        //{
        //    Tuple<bool, LoginViewModel> result = JWTUtil.ValidateLogin(HttpContext.Current.Request);
        //    if (!result.Item1)
        //    {
        //        return new ResponseResult() { Success = false, ErrorMsg = "请登录" };
        //    }
        //    return new ResponseResult() { Success = true, Data = result.Item2.LoginName + "用户资料" };
        //}
        #endregion

        #region GetUserInfo()加上JWT+Filter用户登录校验
        [MyAuth]
        [Route("GetUserInfo")]
        public ResponseResult GetUserInfo()
        {
            UserIdentity userIdentity = (UserIdentity)User.Identity;
            int code = GetStatusCode(userIdentity.Expiration, ConfigUtil.TokenCacheMinutes);
            return new ResponseResult() { Success = true, Data = userIdentity.Id + "用户资料", Code = code };
        }
        #endregion

        #region 解决用户访问过程中token过期的问题
        [MyAuth]
        [HttpGet]
        [Route("RefreshToken")]
        public ResponseResult RefreshToken()
        {
            string userInfo = JWTUtil.Decode(HttpContext.Current.Request.Headers["token"]);
            LoginViewModel loginViewModel = JsonConvert.DeserializeObject<LoginViewModel>(userInfo);
            if (loginViewModel != null)
            {
                if (DateTime.Now > loginViewModel.Expiration && DateTime.Now <= loginViewModel.Expiration.AddMinutes(ConfigUtil.TokenCacheMinutes))
                {
                    loginViewModel.Expiration = DateTime.Now.AddMinutes(ConfigUtil.TokenValidMinutes);
                    return new ResponseResult() { Success = true, Data = JWTUtil.Encode(loginViewModel), Code = 200 };
                }
                return new ResponseResult() { Success = false, Data = JWTUtil.Encode(loginViewModel) };
            }
            return new ResponseResult() { Success = true, Data = "" };
        }
        #endregion

        private int GetStatusCode(DateTime expiration, int tokenCacheMinutes)
        {
            if (expiration < DateTime.Now)
            {
                if (expiration.AddMinutes(tokenCacheMinutes) < DateTime.Now)
                {
                    //token已失效+不在缓冲期内
                    return 9002;
                }
                else
                {
                    //token已失效+在缓冲期内
                    return 9001;
                }
            }
            return 200;
        }
    }
}
